﻿using DataMgr.mode;
using DataMgr.msg;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace DataMgr.File
{
    /// <summary>
    /// bdf文件适配
    /// </summary>
    class BdfAdapter
    {
        private FileStream m_fileR = null;
        private BDFHead m_head = new BDFHead();
        private ChannelDeviceInfo m_chlInfo = new ChannelDeviceInfo();  //通道基本信息
        private List<SingleHisLogData> m_logs = new List<SingleHisLogData>();   //通道日志
        private int m_nOneRdSize = Marshal.SizeOf(typeof(SingleHisDfData));    //一条记录数据的长度
        private FileRecordsRead m_recordControl = new FileRecordsRead();    //记录读取器
        private DataStatistics m_dataStatistics = new DataStatistics();     //统计信息
        private CycleDivideKind m_cycleKind;
        private BmsStepFileInfo m_stepInfo = new BmsStepFileInfo();
        private List<SingleStepInfo> m_stepData = new List<SingleStepInfo>();
        public UInt32 StepFileType { get; set; }    //工步文件类型
        public Int32 StepFileVer { get; set; }      //工步文件版本

        public bool Open(string path, CycleDivideKind cycleKind,ushort startStepId=1, ushort steps=4)
        {
            m_fileR = new FileStream(path, FileMode.Open, FileAccess.Read);
            if (!m_fileR.CanRead)
                return false;

            if (m_fileR.Length > Marshal.SizeOf(m_head))//Marshal.SizeOf(typeof(BDFHead)
            {
                byte[] bytData = new byte[Marshal.SizeOf(m_head)];
                m_fileR.Read(bytData, 0, bytData.Length);
                m_head = (BDFHead)DaFileElement.RawDeserialize(bytData, typeof(BDFHead));
            }
            else
                return false;

            if (m_head.usVersion < (ushort)BDF_Version.BDF_Ver1 || m_head.usVersion > (ushort)BDF_Version.BDF_Ver3)
            {
                MsgUtil.WriteLog("文件版本错误,"+ m_head.usVersion.ToString());
                return false;
            }

            ReadStepInfo();
            if (!ReadChlInfo())
                return false;

            if (!ReadChlLog())
                return false;

            if (m_head.usVersion == (ushort)BDF_Version.BDF_Ver3)
            {
                m_fileR.Seek((long)m_head.piRecordsInfo.lluStart + m_nOneRdSize, SeekOrigin.Begin);
                int btFlag = m_fileR.ReadByte();

                m_nOneRdSize += 1;
                if (btFlag == 1)
                {
                    BmsHisData bmsInfo = new BmsHisData();
                    m_fileR.Seek((long)m_head.piRecordsInfo.lluStart + m_nOneRdSize, SeekOrigin.Begin);
                    byte[] bytData = new byte[4*2];
                    m_fileR.Read(bytData, 0, bytData.Length);
                    bmsInfo.StDataCount = BitConverter.ToUInt16(bytData,0);
                    bmsInfo.VolCount = BitConverter.ToUInt16(bytData, 2);
                    bmsInfo.TempCount = BitConverter.ToUInt16(bytData, 4);
                    bmsInfo.SelfCount = BitConverter.ToUInt16(bytData, 6);

                    m_nOneRdSize += 2 * 4;
                    m_nOneRdSize += Marshal.SizeOf(typeof(DInfo)) * (bmsInfo.SelfCount + bmsInfo.StDataCount) +
                        Marshal.SizeOf(typeof(SingleInfo)) * (bmsInfo.VolCount + bmsInfo.TempCount);
                }
            }

            m_recordControl.OpenFile(path, m_head.piRecordsInfo.lluStart,
                m_head.piRecordsInfo.lluStart + m_head.piRecordsInfo.lluLen - 1, (UInt32)m_nOneRdSize);
            m_dataStatistics.RecordReader = m_recordControl;    //传递记录读取对象
            ReadStepStatis();

            //统计循环信息
            m_cycleKind = cycleKind;
            if (CycleDivideKind.Cycle_CycleID == cycleKind)
            {
                m_dataStatistics.CreateCyclesByCycleID();
            }
            else if (CycleDivideKind.Cycle_StartStep == cycleKind)
            {
                m_dataStatistics.CreateCycleByStepCount(steps, startStepId);
            }
            else
                m_dataStatistics.CreateCycleByChargeStep(cycleKind == CycleDivideKind.Cycle_ChargeStep);

            return true;
        }

        private bool ReadChlInfo()
        {
            if (m_head.usVersion == (ushort)BDF_Version.BDF_Ver1)
            {
                MsgUtil.WriteLog("第一版DA文件,通道信息TODO" );
                return true;
            }
            else if ((m_head.usVersion == (ushort)BDF_Version.BDF_Ver2 || m_head.usVersion == (ushort)BDF_Version.BDF_Ver3))
            {
                m_fileR.Seek((long)m_head.piChannelInfo.lluStart, SeekOrigin.Begin);
                byte[] bytData = new byte[Marshal.SizeOf(m_chlInfo)];
                m_fileR.Read(bytData, 0, bytData.Length);
                m_chlInfo = (ChannelDeviceInfo)DaFileElement.RawDeserialize(bytData, typeof(ChannelDeviceInfo));
                if (m_head.usVersion == (ushort)BDF_Version.BDF_Ver2)
                {
                    m_chlInfo.chlId = (byte)BitConverter.ToChar(bytData, 128 + 32 + 32 + 32 + 2);
                    m_chlInfo.pallelCount = (byte)BitConverter.ToChar(bytData, 128 + 32 + 32 + 32 + 1);
                    m_chlInfo.testId = BitConverter.ToUInt32(bytData, 128 + 32 + 32 + 32 + 3);
                }
            }
            else
                return false;

            return true;
        }

        private void ReadStepInfo()
        {
            m_fileR.Seek((long)m_head.piStepsData.lluStart, SeekOrigin.Begin);
            byte[] bytData = new byte[8];//new byte[m_head.piStepsData.lluLen];
            m_fileR.Read(bytData, 0, bytData.Length);
            StepFileType = BitConverter.ToUInt32(bytData, 0);
            StepFileVer = BitConverter.ToInt32(bytData, 4);
            //读取工步信息
            if (StepFileVer < (int)STEP_Version.VERSION_STEP_FILE_3)
            {
                StepFileInfo sInfo1 = new StepFileInfo();
                byte[] bytData1 = new byte[Marshal.SizeOf(sInfo1)];
                m_fileR.Read(bytData1, 0, bytData1.Length);
                sInfo1 = (StepFileInfo)DaFileElement.RawDeserialize(bytData1, typeof(StepFileInfo));
                Export.BdfDataTransfer.TransStepInfo(sInfo1, ref m_stepInfo);
            }
            else if (StepFileVer == (int)STEP_Version.VERSION_STEP_FILE_3)
            {
                byte[] bytData1 = new byte[Marshal.SizeOf(m_stepInfo)];
                m_fileR.Read(bytData1, 0, bytData1.Length);
                m_stepInfo = (BmsStepFileInfo)DaFileElement.RawDeserialize(bytData1, typeof(BmsStepFileInfo));
            }

            int nStepCount = 0;
            if (m_head.usVersion == (UInt16)BDF_Version.BDF_Ver2 || m_head.usVersion == (UInt16)BDF_Version.BDF_Ver3)
            {
                m_fileR.Read(bytData, 0, bytData.Length);
                nStepCount = BitConverter.ToInt32(bytData, 0);
                int nDataLen = BitConverter.ToInt32(bytData, 4);
            }

            //读取工步数据
            ReadStepData2(nStepCount);
            
        }

        private bool ReadChlLog()
        {
            ulong oneLogSize = (ulong)Marshal.SizeOf(typeof(SingleHisLogData));
            if (m_head.piLogsInfo.lluLen % oneLogSize != 0)
            {
                MsgUtil.WriteLog(string.Format("日志长度错误{0},{1}", m_head.piLogsInfo.lluLen, 
                    Marshal.SizeOf(typeof(SingleHisLogData))));
                return false;
            }

            ulong logCount = m_head.piLogsInfo.lluLen / oneLogSize;
            m_fileR.Seek((long)m_head.piLogsInfo.lluStart, SeekOrigin.Begin);
            for (ulong i = 0; i < logCount; i++)
            {
                SingleHisLogData log = new SingleHisLogData();
                byte[] bytData = new byte[oneLogSize];
                m_fileR.Read(bytData, 0, bytData.Length);
                log = (SingleHisLogData)DaFileElement.RawDeserialize(bytData, typeof(SingleHisLogData));
                m_logs.Add(log);
            }
            return true;
        }

        private bool ReadStepStatis()
        {
            if (m_head.piStepsInfo.lluLen > 0)
            {
                ulong oneStSize = (ulong)Marshal.SizeOf(typeof(STEP_STATIS));
                if (m_head.piStepsInfo.lluLen % oneStSize != 0)
                {
                    MsgUtil.WriteLog(string.Format("工步统计长度错误{0},{1}", m_head.piStepsInfo.lluLen,
                        Marshal.SizeOf(typeof(STEP_STATIS))));
                    return false;
                }

                ulong stCount = m_head.piStepsInfo.lluLen / oneStSize;
                m_fileR.Seek((long)m_head.piStepsInfo.lluStart, SeekOrigin.Begin);
                List<STEP_STATIS> listSteps = new List<STEP_STATIS>();
                for (ulong i = 0; i < stCount; i++)
                {
                    STEP_STATIS st = new STEP_STATIS();
                    byte[] bytData = new byte[oneStSize];
                    m_fileR.Read(bytData, 0, bytData.Length);
                    st = (STEP_STATIS)DaFileElement.RawDeserialize(bytData, typeof(STEP_STATIS));
                    listSteps.Add(st);
                }

                m_dataStatistics.SetStepStatis(listSteps);
                MsgUtil.WriteLog(string.Format("工步统计{0}", listSteps.Count));
            }

            return true;
        }
       
        private void ReadStepData2(int nStepCount)
        {
            int nPos = 0;
            for (int i = 0; i < nStepCount; ++i)
            {
                SingleStepInfo oneStep = new SingleStepInfo();
                byte[] bytData = new byte[8];//new byte[m_head.piStepsData.lluLen];
                m_fileR.Read(bytData, 0, bytData.Length);
                oneStep.StepNo = BitConverter.ToInt32(bytData, 0);

                oneStep.StepName = (byte)m_fileR.ReadByte();

                byte[] btInt = new byte[4];
                m_fileR.Read(btInt, 0, btInt.Length);
                oneStep.ParamDataCount = BitConverter.ToInt32(btInt, 0);
                if (oneStep.ParamDataCount > 0)
                {
                    oneStep.StepParams = new double[oneStep.ParamDataCount];
                    byte[] btDouble = new byte[8* oneStep.ParamDataCount];
                    m_fileR.Read(btDouble, 0, btDouble.Length);
                    for (int k = 0; k < oneStep.ParamDataCount; k++)
                    {
                        oneStep.StepParams[k] = BitConverter.ToDouble(btDouble, 8 * k);
                    }
                }

                oneStep.CutOffConditionCount = (byte)m_fileR.ReadByte();
                oneStep.CutOffConditions = new CutOffCondition[oneStep.CutOffConditionCount]; 
                for (int k = 0; k < oneStep.CutOffConditionCount; k++)
                {
                    if (StepFileVer < (int)STEP_Version.VERSION_STEP_FILE_3)
                    {
                        StopCond sCond = new StopCond();
                        byte[] btCond = new byte[Marshal.SizeOf(sCond)];
                        m_fileR.Read(btCond, 0, btCond.Length);
                        sCond = (StopCond)DaFileElement.RawDeserialize(btCond, typeof(StopCond));
                        Export.BdfDataTransfer.TransStepCond(sCond, ref oneStep.CutOffConditions[k]);
                    }
                    else
                    {
                        byte[] btCond = new byte[Marshal.SizeOf(oneStep.CutOffConditions[k])];
                        m_fileR.Read(btCond, 0, btCond.Length);
                        oneStep.CutOffConditions[k] = (CutOffCondition)DaFileElement.RawDeserialize(btCond, typeof(CutOffCondition));
                    }
                }

                oneStep.RecordConditionCount = (byte)m_fileR.ReadByte();
                oneStep.RecordConditions = new RecordCondition[oneStep.RecordConditionCount];
                for (int k = 0; k < oneStep.RecordConditionCount; k++)
                {
                    byte[] btCond = new byte[Marshal.SizeOf(typeof(RecordCondition))];
                    m_fileR.Read(btCond, 0, btCond.Length);
                    oneStep.RecordConditions[k] = (RecordCondition)DaFileElement.RawDeserialize(btCond, typeof(RecordCondition));
                }

                if (StepFileVer >= (int)STEP_Version.VERSION_STEP_FILE_2)
                {
                    m_fileR.Read(btInt, 0, btInt.Length);
                    oneStep.ExpandParamCount = BitConverter.ToInt32(btInt, 0);
                    oneStep.ExpandParams = new ExpandParam[oneStep.ExpandParamCount];
                    for (int k = 0; k < oneStep.RecordConditionCount; k++)
                    {
                        ExpandParam expandParam = new ExpandParam();
                        m_fileR.Read(btInt, 0, btInt.Length);
                        expandParam.ExpandParamType = BitConverter.ToInt32(btInt, 0);
                        m_fileR.Read(btInt, 0, btInt.Length);
                        expandParam.ExpandParamParamCount = BitConverter.ToInt32(btInt, 0);
                        byte[] btDouble = new byte[8 * expandParam.ExpandParamParamCount];
                        m_fileR.Read(btDouble, 0, btDouble.Length);
                        expandParam.ExpandParamParamValues = new double[expandParam.ExpandParamParamCount];
                        for (int j = 0; j < expandParam.ExpandParamParamCount; j++)
                        {
                            expandParam.ExpandParamParamValues[j] = BitConverter.ToDouble(btDouble, 8 * k);
                        }

                        oneStep.ExpandParams[k] = expandParam;
                    }
                }
                m_stepData.Add(oneStep);
            }
        }
        public BdfRecord GetCurRecord(UInt32 dwFromIndex)
        {
            return m_recordControl.GetCurRecord(dwFromIndex);
        }
        public List<CycleStatisticsNode> GetCycles()
        {
            return m_dataStatistics.GetCycles();
        }
        public StepStatisticsNode GetStepNode(int stepIndex)
        {
            return m_dataStatistics.GetStepNode(stepIndex);
        }
        public List<SingleHisLogData> GetLogs()
        {
            return m_logs;
        }

        public BmsStepFileInfo GetStepInfo()
        {
            return m_stepInfo;
        }

        public List<SingleStepInfo> GetStepData()
        {
            return m_stepData;
        }

        public ChannelDeviceInfo GetChlInfo()
        {
            return m_chlInfo;
        }
    }
}
